<?php
declare (strict_types=1);

namespace app\user\logic\user;

use app\common\exception\LogicException;
use app\common\model\payment\PaymentOrder as CommonOrder;
use app\common\model\ProductType;
use app\course\logic\base\Course;
use app\course\logic\coupon\{CouponUser};
use app\course\model\payment\{PaymentOrder, PaymentOrderItem as POI, PaymentOrderItemCoupon as POIC};
use app\mall\logic\product\Product;
use app\promotion\logic\{Promotion};
use app\school\logic\school\School;
use ArrayObject;
use Exception;
use think\facade\Db;

/**
 * 个人订单接口类
 */
class Order extends PaymentOrder
{

    /**
     * 获取订单
     * Author 亓官雨树<lucky.max@foxmail.com>
     * Date：   2020-05-07
     */
    public function getOrders($type, array $param)
    {
        // 数据验证
        $this->getValidate()->scene('orders')->failException()->check($param);
        // 参数
        $date = $param['date'] ?? '';
        $mid  = request()->mid;
        // 去除会员，积分，余额充值订单
        $ids = ProductType::getProductIdStrByKeys(['vip', 'credit', 'balance']);
        // 订单状态text
        $text = $this->getStatusText();

        switch ($type) {
            case 'finish':
                $mod = $this->where('__TABLE__.status', 'IN', '20,30,40,50');
                break;

            case 'cancel':
                $mod = $this->where('__TABLE__.status', 0);
                break;

            case 'waiting':
                $mod = $this->where('__TABLE__.status', 10);
                break;

            default:
                $mod = $this;
                break;
        }
        $mod = $mod->join('payment_order_item i', '__TABLE__.order_no=i.order_no')->where('__TABLE__.user_id', $mid);
        // $mod = $mod->withJoin(['item_many'])->where('item_many.user_id', $mid);
        switch ($date) {
            case 'this_year':
                $mod = $mod->where('i.update_time', '>', strtotime(date('Y', time()) . '-1-1'));
                break;

            case 'earlier':
                $mod = $mod->where('i.update_time', '<', strtotime(date('Y', time()) . '-1-1'));
                break;

            default:
                if ($date) {
                    $mod = $mod->where('i.update_time', '>', strtotime(date('Y-m-d', strtotime('-' . $date))));
                }
                break;
        }
        return $mod->field('__TABLE__.*,i.product_type_id,i.credit,i.ext_data')->where('product_type_id', 'NOT IN', $ids)->group('__TABLE__.order_no')->order('__TABLE__.order_no', 'DESC')->withCount(['item_many' => 'item_count'])->with(['promotion'])
            // ->buildSql();
            ->paginate(static::getListRows())->each(function ($item) use ($text) {
                if ($item->status == 10 && $item->promotion && $item->close_time && $item->close_time < time()) {
                    $item->status = 60;
                    $item->save();
                }
                $item->credit      = $item->credit ? json_decode($item->credit) : new ArrayObject();
                $item->ext_data    = $item->ext_data ? json_decode($item->ext_data) : new ArrayObject();
                $item->status_text = $text[$item['status']];
                // 单个产品可以是课程、考试、商品等
                if ($item->item_count == 1) {
                    $item->order_type = $item->itemOne->product_type_id;
                    $product          = $this->getProductInfo($item->itemOne);
                    $item->products   = [$product];
                    unset($item->itemOne);
                } else if ($item->item_count) {
                    $item->order_type = 0; // 订单类型为课程
                    $orders           = app(POI::class)->where('order_no', $item->order_no)->field('product_id,expire_time,payment')->select();
                    $products         = [];
                    foreach ($orders as $order) {
                        $products[] = app(Course::class)->getProductInfo($order);
                    }
                    $item->products = $products;
                }
                if ($item->product_type_id == 11) {
                    $fictitious       = array_column($item->products, 'fictitious');
                    $item->fictitious = current($fictitious);
                }
                // 活动
                $item->promotion_id        = $item->promotion ? $item->promotion->id : 0;
                $item->promorion_type      = $item->promotion ? $item->promotion->type : 0;
                $item->promorion_type_text = $item->promotion ? $item->promotion->type_text : '';
                unset($item->promotion);
            });
    }

    public function getOrderInfo($orderNo)
    {
        $obj = new ArrayObject();
        // 订单状态text
        $text = $this->getStatusText();
        $info = app(CommonOrder::class)->join('payment_order_item i', '__TABLE__.order_no=i.order_no')->where('i.order_no', $orderNo)->field('__TABLE__.*,i.product_type_id,i.credit,i.ext_data')->with(['promotion', 'payway'])->withCount(['item_many' => 'item_count'])->findOrEmpty();

        $info->credit      = $info->credit ? json_decode($info->credit) : $obj;
        $info->ext_data    = $info->ext_data ? json_decode($info->ext_data) : $obj;
        $info->status_text = $text[$info['status']];
        // 单个产品可以是课程、考试、商品等
        if ($info->item_count == 1) {
            $info->order_type = $info->product_type_id;
            $product          = $this->getProductInfo($info->itemOne);
            $info->products   = [$product];
            $info->mhm        = app(School::class)->getSchoolTitle($product->mhm_id);
            unset($info->itemOne);
        } else if ($info->item_count) {
            $info->order_type = 0; // 订单类型为课程
            $orders           = app(POI::class)->where('order_no', $info->order_no)->field('product_id,expire_time,payment')->select();
            $products         = [];
            $mhm              = [];
            foreach ($orders as $order) {
                $course     = app(Course::class)->getProductInfo($order);
                $products[] = $course;
                $mhm[]      = $course->school_name;
            }
            $info->products = $products;
            $info->mhm      = implode('，', array_unique($mhm));
        }
        if ($info->product_type_id == 11) {
            $fictitious       = array_column($info->products, 'fictitious');
            $info->fictitious = current($fictitious);
        } else {
            $price             = array_sum(array_column($info->products, 'price'));
            $info->total_price = $price;
            $info->fee_price   = bcsub(strval($price), $info->payment, 2);
        }
        // 活动
        $info->promotion_id        = $info->promotion ? $info->promotion->id : 0;
        $info->promorion_type      = $info->promotion ? $info->promotion->type : 0;
        $info->promorion_type_text = $info->promotion ? $info->promotion->type_text : '';
        unset($info->promotion);
        $info = $info->toArray();

        $info['addrinfo'] = $info['addrinfo'] ?: $obj;

        return $info;
    }

    /**
     * 获取产品信息
     * Author 亓官雨树<lucky.max@foxmail.com>
     * Date：   2020-05-09
     */
    protected function getProductInfo($orderItem)
    {
        $product_class = [
            1  => '\\app\\course\\logic\\base\\Course',
            5  => '\\app\\course\\logic\\base\\CourseSection',
            8  => '\\app\\exam\\logic\\Examination',
            9  => '\\app\\exam\\logic\\Special',
            10 => '\\app\\exam\\logic\\Rollup',
            11 => '\\app\\mall\\logic\\product\\Product',
        ];

        $type = $orderItem->product_type_id;

        $course = Course::getCourseProducts();
        if ($orderItem->section_id > 0) {
            $type = 5;
        } else if (in_array($type, $course)) {
            $type = 1;
        }

        $classname = $product_class[$type];

        if (class_exists($classname) && method_exists($classname, 'getProductInfo')) {
            return app($classname)->getProductInfo($orderItem);
        }
        return new ArrayObject();
    }

    /**
     * 取消订单
     * Author 亓官雨树<lucky.max@foxmail.com>
     * Date：   2020-05-09
     *
     */
    public function cancel($order_no)
    {
        $order = $this->where('order_no', $order_no)->with(['redeemCreditSub'])->findOrFail();
        if ($order->status == 0) return $order;

        Db::startTrans();
        try {
            $order->status = 0;
            if (!$order->save()) throw new LogicException('操作失败');
            // 子订单数据
            $poi = app(POI::class)->where('order_no', $order->order_no)->findOrEmpty();
            // 检查活动
            if (!$poi->isEmpty() && $poi->promotion_id) {
                app(Promotion::class)->deleteUserPromotion(intval($poi->promotion_id), intval($poi->user_id));
            }
            // 检查积分
            if (count($order->redeemCreditSub)) {
                // 退还积分
                app(Credit::class)->returnOrderCredit($order);
            }
            // 处理卡券退还
            $coupon_ids = app(POIC::class)->alias('c')->join('payment_order_item i', 'i.order_sub_no=c.order_sub_no')->where('i.order_no', $order_no)->group('coupon_id')->column('coupon_id');
            if (count($coupon_ids)) {
                app(CouponUser::class)->returnOrderCoupon($order->user_id, implode(',', $coupon_ids));
            }
            // 商品订单，恢复库存
            if ($poi->product_type_id == 11) {
                $prod            = app(Product::class)->findOrEmpty($poi->product_id);
                $prod->stock_num += $poi->ext_data->num;
                if (!$prod->save()) throw new LogicException('操作失败');
            }
            Db::commit();
        } catch (LogicException|Exception $e) {
            Db::rollback();
            throw new LogicException($e->getMessage());
        }

        return $this->where('order_no', $order_no)->findOrFail();
    }

    /**
     * 删除订单
     * Author 亓官雨树<lucky.max@foxmail.com>
     * Date：   2020-05-09
     */
    public function softDel($order_no): bool
    {
        $order = $this->where('order_no', $order_no)->findOrFail();
        return $order->delete();
    }
}
